<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Running long JavaScript processes in a web browser (optimized version)</title>
<script>
(function () {

    var i, length, data, el, out, busy, globalStart;
    
    var sort = function() {
        var j, value, start;
        var _i = i;
        var _data = data;
  
        start = new Date().getTime();
        for (; _i < length; _i++) {
  
            for (j = length; j > _i; j--) {
                if (_data[j] < _data[j - 1]) {
                    value = _data[j];
                    _data[j] = _data[j - 1];
                    _data[j - 1] = value;
                }
            }
  
            if (new Date().getTime() - start > 100) {
                _i++;
                setTimeout(sort, 0);
                break;
            }
        }
  
        el.style.width = (100 * _i / length) + "%";
        if (_i >= length) {
            el.innerHTML = "Total duration: " + ((new Date().getTime() - globalStart) / 1000) + " seconds";
            out.innerHTML = _data+"";        
            busy.innerHTML = "Done!";        
        }

        i = _i;
    };

    var pure_sort = function() {
        var j, value, start;
        var _data = data;
  
        start = new Date().getTime()
        for (var _i = 0; _i < length; _i++) {
  
            for (j = length; j > _i; j--) {
                if (_data[j] < _data[j - 1]) {
                    value = _data[j];
                    _data[j] = _data[j - 1];
                    _data[j - 1] = value;
                }
            }
        }
        progressFn(_i, length);  
    };
    
    var oldsort = function() {
        var j, value, start;
  
        start = new Date().getTime()
        for (; i < length; i++) {
  
            for (j = length; j > i; j--) {
                if (data[j] < data[j - 1]) {
                    value = data[j];
                    data[j] = data[j - 1];
                    data[j - 1] = value;
                }
            }
  
            if (new Date().getTime() - start > 40) {
                i++;
                setTimeout(arguments.callee, 0);
                break;
            }
        }
  
        progressFn(i, length);
  
    };
    
    var progressFn = function(value, total) {
        el.style.width = (100 * value / total) + "%";
        if (value >= total) {
            el.innerHTML = "Total duration: " + ((new Date().getTime() - globalStart) / 1000) + " seconds";
            out.innerHTML = data+"";
            busy.innerHTML = "Done!";        
        }
    }
    
    
    var setup = function() {
      var size = document.getElementById("size").value;
      var timeslice = document.getElementById("slice").value;
      var isRandom = !!document.getElementById("randomize").checked;
      
      length = size;
      data = [];
      
      el = document.getElementById("progressbar").firstChild;
      out = document.getElementById("out");
      busy = document.getElementById("busy");
      
      el.innerHTML = "";
      el.style.width = "0";
      busy.innerHTML = "Setup complete, press run to start...";
  
      // Setup an array of random integers...
      for (i = 0; i < length; i++) {
          data[i] = isRandom ?
              Math.floor(Math.random() * length) :
              length-i;
      }
  
      i = 0;
    }

    
    var run = function(){
      busy.innerHTML = "Sorting, please wait...";
      globalStart = new Date().getTime();
      setTimeout(sort, 0);
    }
    
    window.onload = function() {
      setup();
      document.getElementById("run").onclick = run;
      document.getElementById("setup").onclick = setup;
    }
    


})();

</script>
<style>

body {
  padding:0;
  margin:1em;
}

#progressbar {
  position:relative;
  width:300px; height:20px;
  border:1px solid black;
  margin: 2em 0 0.5em;
  overflow:hidden;
}

#progressbar div {
  background:#316AC5;
  width:0; height:100%;
  color: #fff;
  text-indent: 10px;
}

#out {
  background: #def;
  border: 1px solid #789;
  margin-left: -2px;
  font: 10px Arial;
  height: 32px;
  width: 100%;
  overflow: auto;
}

#buttons{
  text-align: center;
}
.label{
  text-align: right;
}
</style>
</head>
<body>

  <h2>Settings</h2>
  <form>
  <table>
    <tr>
      <td class="label">Size</td>
      <td><input id="size" type="text" value="2500"/></td>
    </tr>
    <tr>
      <td class="label">Time slice</td>
      <td><input id="slice" type="text" value="50"/></td>
    </tr>
    <tr>
      <td class="label">Randomize</td>
      <td><input id="randomize" type="checkbox" /></td>
    </tr>
    <tr>
      <td class="label">Method</td>
      <td>
        <input name="method" value="optimized" type="radio" checked="checked" />optimized frame skipping<br/>
        <input name="method" value="frameskip" type="radio" />frame skipping<br/>
        <input name="method" value="noframeskip" type="radio" />no frame skipping<br/>
        <input name="method" value="puresort" type="radio" />pure sort<br/>
      </td>
    </tr>
    <tr>
      <td colspan="2" id="buttons">
        <input id="setup" type="button" value="reset" />
        <input id="run" type="button" value="run" />
      </td>
    </tr>
  </table>
  </form>
  
  <h2>Result</h2>

  <div id="busy">&nbsp;</div>
  <div id="progressbar"><div style="width: 0;"></div></div>
  <div id="out"></div>

</body>
</html>